package com.hz.api.admin.web.util;

import java.util.*;
import java.util.stream.Collectors;

public class TeamSplitterUtil {

    // Function to find the best splits for a given set of 10 weights
    public static List<Split> findBestSplits(Map<String, Double> weights) {
        List<Map.Entry<String, Double>> entries = new ArrayList<>(weights.entrySet());
        int n = entries.size();
        int half = n / 2;
        List<Split> splits = new ArrayList<>();

        // Generate all possible 5-player teams from the 10 selected players
        List<List<Map.Entry<String, Double>>> teamCombinations = generateCombinations(entries, half);

        for (List<Map.Entry<String, Double>> team1 : teamCombinations) {
            Set<String> team1Names = new HashSet<>();
            for (Map.Entry<String, Double> entry : team1) {
                team1Names.add(entry.getKey());
            }

            List<Map.Entry<String, Double>> team2 = new ArrayList<>();
            for (Map.Entry<String, Double> entry : entries) {
                if (!team1Names.contains(entry.getKey())) {
                    team2.add(entry);
                }
            }

            Double sumTeam1 = team1.stream().mapToDouble(Map.Entry::getValue).sum();
            Double sumTeam2 = team2.stream().mapToDouble(Map.Entry::getValue).sum();
            Double diff = Math.abs(sumTeam1 - sumTeam2);

            splits.add(new Split(team1, team2, diff));
        }

        // Sort the splits by the difference in ascending order
        splits.sort(Comparator.comparingDouble(Split::getDifference));

        // Get the top 10 splits
        return splits.size() > 5 ? splits.subList(0, 5) : splits;
    }

    // Helper class to store split information and its difference
    public static class Split {
        public final List<Map.Entry<String, Double>> team1;
        public final List<Map.Entry<String, Double>> team2;
        public final Double difference;

        public Split(List<Map.Entry<String, Double>> team1, List<Map.Entry<String, Double>> team2, Double difference) {
            this.team1 = team1;
            this.team2 = team2;
            this.difference = difference;
        }

        public List<Map.Entry<String, Double>> getTeam1() {
            return team1;
        }

        public List<Map.Entry<String, Double>> getTeam2() {
            return team2;
        }

        public Double getDifference() {
            return difference;
        }


        @Override
        public String toString() {
            return "Split{" +
                    "team1=" + team1 +
                    ", team2=" + team2 +
                    ", difference=" + difference +
                    '}';
        }
    }

    // Function to extract names from team entries
    public static List<String> extractNames(List<Map.Entry<String, Double>> team) {
        List<Map.Entry<String, Double>> sortTeam = team.stream().sorted((x,y)->y.getValue().compareTo(x.getValue())).collect(Collectors.toList());
        List<String> names = new ArrayList<>();
        for (Map.Entry<String, Double> entry : sortTeam) {
            names.add(entry.getKey());
        }
        return names;
    }

    // Function to generate all combinations of a given size from a list
    public static <T> List<List<T>> generateCombinations(List<T> list, int size) {
        List<List<T>> result = new ArrayList<>();
        generateCombinationsHelper(list, size, 0, new ArrayList<>(), result);
        return result;
    }

    public static <T> void generateCombinationsHelper(List<T> list, int size, int start, List<T> current, List<List<T>> result) {
        if (current.size() == size) {
            result.add(new ArrayList<>(current));
            return;
        }

        for (int i = start; i < list.size(); i++) {
            current.add(list.get(i));
            generateCombinationsHelper(list, size, i + 1, current, result);
            current.remove(current.size() - 1);
        }
    }

    public static void main(String[] args) {
        // Example usage with pre-selected 10 players
        Map<String, Double> weights = new HashMap<>();
        weights.put("赵雷", 91d);
        weights.put("李强", 93d);
        weights.put("司马缸", 82d);
        weights.put("杨运", 79d);
        weights.put("小虎", 76d);
        weights.put("黄超", 79d);
//        weights.put("北海", 77);
//        weights.put("先锋官", 78);
        weights.put("德芙", 69d);
//        weights.put("可比克", 72);
//        weights.put("短腿", 73);
        weights.put("阿健", 70d);
        weights.put("老谢", 69d);
        weights.put("徐阳", 78d);
//        weights.put("Jack", 91);

        List<Split> results = findBestSplits(weights);
        Split split = results.get(new Random().nextInt(results.size()));
        List<String> team1 = extractNames(split.getTeam1());
        List<String> team2 = extractNames(split.getTeam2());

        for (Split result : results) {
            System.out.println(extractNames(result.getTeam1()));
            System.out.println(extractNames(result.getTeam2()));
            System.out.println(result.difference);
        }
        System.out.println(team1);
        System.out.println(team2);


    }
}
